﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using Javavaj.iHunter;
using Javavaj.iHunter.Database;


namespace Javavaj.iHunter.Core
{
    public struct PluginSettingItem : IEquatable<PluginSettingItem>
    {

        public string AssemblyName { get; set; }
        public bool Enabled { get; set; }
        public XmlDocument Settings { get; set; }


        public bool Equals(PluginSettingItem other)
        {
            return AssemblyName == other.AssemblyName &&
                Enabled == other.Enabled
                ;

        }
    };

    public partial class PluginSettings : IDictionary<string, PluginSettingItem>
    {
        public PluginSettings(UserDbDataSet dataSet)
        {
            this.dataSet = dataSet;
        }
        UserDbDataSet dataSet;

        PluginSettingItem? GetSetting(string assemblyName)
        {
            foreach (var item in this)
            {
                if (item.Key == assemblyName)
                    return item.Value;

            }
            return null;
        }
        void SetSetting(string assemblyName, PluginSettingItem settings)
        {
            var rows = (from row in dataSet.PluginSettings
                        where row.AssemblyName == assemblyName
                        select row).ToArray();
            if (rows.Length == 0)
                AddSetting(assemblyName, settings);
            else
            {
                rows[0].Enabled = settings.Enabled;
                rows[0].Settings = settings.Settings.OuterXml;

                rows[0].AcceptChanges();
            }

        }

        void AddSetting(string assemblyName, PluginSettingItem settings)
        {
            var rows = (from row in dataSet.PluginSettings
                        where row.AssemblyName == assemblyName
                        select row).ToArray();

            if (rows.Length == 0)
            {
                var row = dataSet.PluginSettings.NewPluginSettingsRow();
                row.AssemblyName = assemblyName;
                row.Enabled = settings.Enabled;
                row.Settings = settings.Settings.OuterXml;
                row.AcceptChanges();
            }
            else
            {
                throw new InvalidOperationException();
            }

        }

        bool DeleteSetting(string assemblyName)
        {
            var rows = (from row in dataSet.PluginSettings
                        where row.AssemblyName == assemblyName
                        select row).ToArray();
            if (rows.Count() == 0)
                return false;

            foreach (var row in rows)
                row.Delete();
            dataSet.PluginSettings.AcceptChanges();
            return true;
        }




        #region IDictionary<string,PluginSettingItem> 成员

        public void Add(string key, PluginSettingItem value)
        {
            AddSetting(key, value);
        }

        public bool ContainsKey(string key)
        {
            return (GetSetting(key) != null);
        }

        public ICollection<string> Keys
        {
            get
            {
                var result = from settings in this
                             select settings.Key;
                return result.ToArray();
            }
        }

        public bool Remove(string key)
        {
            return DeleteSetting(key);
        }

        public bool TryGetValue(string key, out PluginSettingItem value)
        {
            var settings = GetSetting(key);
            if (settings.HasValue)
            {
                value = settings.Value;
                return true;
            }
            else
            {
                value = new PluginSettingItem();

                return false;
            }
        }

        public ICollection<PluginSettingItem> Values
        {
            get
            {
                var result = from settings in this
                             select settings.Value;
                return result.ToArray();
            }
        }

        public PluginSettingItem this[string key]
        {
            get
            {
                var result = GetSetting(key);
                return result.Value;
            }
            set
            {
                SetSetting(key, value);
            }
        }

        #endregion

        #region ICollection<KeyValuePair<string,PluginSettingItem>> 成员

        public void Add(KeyValuePair<string, PluginSettingItem> item)
        {
            AddSetting(item.Key, item.Value);
        }

        public void Clear()
        {
            var rows = from row in dataSet.PluginSettings
                       select row;

            foreach (var row in rows)
                row.Delete();

            dataSet.PluginSettings.AcceptChanges();
            return;
        }

        public bool Contains(KeyValuePair<string, PluginSettingItem> item)
        {
            var settings = GetSetting(item.Key);
            return (settings.HasValue && settings.Value.Equals(item.Value));

        }

        public void CopyTo(KeyValuePair<string, PluginSettingItem>[] array, int arrayIndex)
        {
            int index = arrayIndex;
            foreach (KeyValuePair<string, PluginSettingItem> pair in this)
            {
                array[arrayIndex + index] = pair;
                index++;
            }
        }

        public int Count
        {
            get
            {
                return dataSet.PluginSettings.Count;

            }
        }

        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        public bool Remove(KeyValuePair<string, PluginSettingItem> item)
        {
            if (Contains(item))
                return DeleteSetting(item.Key);
            return false;
        }

        #endregion

        #region IEnumerable<KeyValuePair<string,PluginSettingItem>> 成员

        public IEnumerator<KeyValuePair<string, PluginSettingItem>> GetEnumerator()
        {
            var rows = from row in dataSet.PluginSettings
                       select row;
            foreach (var row in rows)
            {
                XmlDocument document = null;
                try
                {
                    document = new XmlDocument();
                    document.LoadXml(row.Settings);
                }
                catch
                {
                    document = null;
                }

                var item = new KeyValuePair<string, PluginSettingItem>(
                    row.AssemblyName,
                    new PluginSettingItem()
                    {
                        AssemblyName = row.AssemblyName,
                        Enabled = row.Enabled,
                        Settings = document
                    });

                yield return item;
            }
            yield break;
        }

        #endregion

        #region IEnumerable 成员

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return ((IEnumerable<KeyValuePair<string, PluginSettingItem>>)this).GetEnumerator() as System.Collections.IEnumerator;
        }

        #endregion
    }
}
